package com.digua.base.util

import java.lang.reflect.Field
import java.util.regex.Pattern

object ObjUtil {
    /**
     * 判断两个数据是否一样
     *
     * @param o1
     * @param o2
     * @return
     */
    fun <T> eqIgnoreCase(o1: T?, o2: T?): Boolean {
        return if (o1 == null || o2 == null) eq(o1, o2) else o1.toString().equals(o2.toString(), ignoreCase = true)
    }

    /**
     * 判断两个数据是否一样
     *
     * @param o1
     * @param o2
     * @return
     */
    fun <T> eq(o1: T, o2: T) = o1 == o2

    /**
     * 判断两个数据是否不一样
     *
     * @param o1
     * @param o2
     * @return
     */
    fun <T> ne(o1: T, o2: T) = o1 != o2

    /**
     * 判断传入参数中是否有包含的
     *
     * @param o1
     * @param o2
     * @return
     */
    fun <T> eqHas(o1: T?, vararg o2: T): Boolean {
        if (o1 == null || o2 == null || o2.size <= 0) {
            return false
        }
        for (t in o2) {
            if (eq(o1, t)) {
                return true
            }
        }
        return false
    }

    /**
     * 判断传入参数中是否有包含的
     *
     * @param o1
     * @param o2
     * @return
     */
    fun <T> eqIgnoreCaseHas(o1: T?, vararg o2: T): Boolean {
        if (o1 == null || o2 == null || o2.size <= 0) {
            return false
        }
        for (t in o2) {
            if (eqIgnoreCase<T>(o1, t)) {
                return true
            }
        }
        return false
    }

    /**
     * 是否为基础数据类型
     *
     * @param t
     * @return
     */
    fun <T> isBaseData(t: T): Boolean {
        return t is Int || t is Double || t is Boolean || t is Float || t is Byte || t is Short || t is Long || t is Char
    }

    /**
     * 是否为基础数据类型包含字符串
     *
     * @param t
     * @return
     */
    fun <T> isBaseDataOrStr(t: T): Boolean {
        return t is String || isBaseData(t)
    }

    /**
     * 是否为基础数据类型
     *
     * @param clz
     * @return
     */
    fun <T> isBaseData(clz: Class<T>): Boolean {
        return eqHas(clz.simpleName,
            Int::class.java.simpleName,
            Double::class.java.simpleName,
            Boolean::class.java.simpleName,
            Float::class.java.simpleName,
            Byte::class.java.simpleName,
            Short::class.java.simpleName,
            Long::class.java.simpleName,
            Char::class.java.simpleName)
    }

    /**
     * 是否为基础数据类型包含字符串
     *
     * @param clz
     * @return
     */
    fun <T> isBaseDataOrStr(clz: Class<T>): Boolean {
        return eqHas(clz.simpleName, String::class.java.simpleName) || isBaseData(clz)
    }

    /**
     * 判断String是否是正数或者负数 如: +1 | 1 | -1 | +0.1 | 0.1 | -0.1 等
     *
     * @param str
     * @return
     */
    fun isNumeric(str: String?): Boolean {
        val pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$")
        return pattern.matcher(str).matches()
    }

    /**
     * 比较两个数据的大小 如果其中一个值为空值，空为小, 当前仅支持基本数据类型
     *
     * @param t1
     * @param t2
     * @param <T>
     * @return 0:一样/相等；1：t1 > t2；-1：t1 < t2
    </T> */
    fun <T> compare(t1: T?, t2: T?): Int {
        if (eq(t1, t2)) {
            return 0
        }
        if (t1 == null) {
            return -1
        }
        if (t2 == null) {
            return 1
        }
        if (isNumeric(t1.toString() + "") && isNumeric(t2.toString() + "")) {
            if (java.lang.Double.valueOf(t1.toString() + "") == java.lang.Double.valueOf(t2.toString() + "")) {
                return 0
            } else if ((t1.toString() + "").toDouble() > (t2.toString() + "").toDouble()) {
                return 1
            } else if ((t1.toString() + "").toDouble() < (t2.toString() + "").toDouble()) {
                return -1
            }
        } else if (isBaseDataOrStr<T>(t1)) {
            return (t1.toString() + "").compareTo(t2.toString() + "")
        }
        return t1.toString().compareTo(t2.toString())
    }

    /**
     * 通过对象的属性名获取属性值
     *
     * @param t
     * @param attrName 属性名
     * @param <T>
     * @param <R>      返回数据类型
     * @return
    </R></T> */
    fun <T, R> getValByAttr(t: T, attrName: String?): R? {
        return getValByAttr<T, R?>(t, attrName, null)
    }

    /**
     * 通过对象的方法名获取方法值
     *
     * @param t
     * @param methodName 方法名
     * @param param      对应方法所要传的参数
     * @param <T>
     * @param <R>        返回数据类型
     * @return
    </R></T> */
    fun <T, R> getValByMethod(t: T, methodName: String?, vararg param: Any?): R {
        return getValByMethod<T, R>(t, methodName, null, *param)
    }

    /**
     * 通过对象的属性名获取属性值
     *
     * @param t
     * @param attrName 属性名
     * @param defVal   默认值
     * @param <T>
     * @param <R>      返回数据类型
     * @return
    </R></T> */
    fun <T, R> getValByAttr(t: T?, attrName: String?, defVal: R): R {
        if (t == null || attrName == null || attrName.trim { it <= ' ' }.length <= 0) {
            return defVal
        }
        try {
            //得到属性
            val field: Field = t.javaClass.getDeclaredField(attrName)
            //打开私有访问
            field.isAccessible = true
            return field[t] as R
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        return defVal
    }

    /**
     * 通过对象的方法名获取方法值
     *
     * @param t
     * @param methodName 方法名
     * @param defVal     默认值
     * @param param      对应方法所要传的参数
     * @param <T>
     * @param <R>        返回数据类型
     * @return
    </R></T> */
    fun <T, R> getValByMethod(t: T?, methodName: String?, defVal: R, vararg param: Any?): R {
        if (t == null || methodName == null || methodName.trim { it <= ' ' }.length <= 0) {
            return defVal
        }
        try {
            for (method in t.javaClass.methods) {
                if (eq(method.name, methodName) && method.typeParameters.size == param.size) {
                    return method.invoke(t, *param) as R
                }
            }
        } catch (e: Exception) {
            LogUtil.e("异常:", e)
        }
        return defVal
    }
}
